from typing import Any
from django.utils import timezone
from datetime import datetime
from rest_framework.request import Request

# Rest Framework package
# from rest_framework import viewsets
# from rest_framework.response import Response
# from rest_framework.views import APIView
from rest_framework.viewsets import ModelViewSet, ViewSet
from rest_framework.response import Response
from rest_framework import status
from rest_framework.decorators import action
from rest_framework.permissions import IsAuthenticated
from rest_framework_simplejwt.authentication import JWTAuthentication
from drf_spectacular.utils import extend_schema_view, extend_schema
import tsl_backend.frontend_api.serializers.serializers as frontend_serializers
import tsl_backend.frontend_api.utils.lib as frontend_lib
import logging, json

# parsing data from the client
# To bypass having a CSRF token
# for sending response to the client

# Task model
from tsl_backend.frontend_api.models.workorder import ProductionActualBOM, Detail
import tsl_backend.frontend_api.models.order_routing as order_routing
import tsl_backend.users.models as users

from tsl_backend.fgr_api.middleware import response as fgr_response

# API definition for task
from tsl_backend.fgr_api.serializers.serializers import (
    ActualBomSerializer,
    DetailSerializer,
    StandardBomSerializer,
    RouteDetailSerializer,
    DiscardDetailSerializer,
)
import tsl_backend.frontend_api.models.route as routes

import tsl_backend.common as common


def is_valid_datetime(date_string):
    """
    Check if a string is a valid datetime.  2001-01-01T00:00:00
    """
    if date_string == "0001-01-01T00:00:00":
        return None
    else:
        formatted_date_string = datetime.strptime(date_string, "%Y-%m-%dT%H:%M:%S")
        # Convert the datetime to the expected format
        iso_date_string = formatted_date_string.isoformat().replace("T", " ")
        return iso_date_string


@extend_schema_view(
    # list=extend_schema(summary='List all foos'),
    create=extend_schema(summary="Create or update order"),
    # retrieve=extend_schema(summary='Retrieve a specific foo'),
    # update=extend_schema(summary='Update a specific foo'),
    # partial_update=extend_schema(summary='Partially update a specific foo'),
    # destroy=extend_schema(summary='Delete a specific foo')
)
class DetailViewSet(ModelViewSet):
    queryset = Detail.objects.none()
    serializer_class = DetailSerializer

    http_method_names = ["post"]
    permission_classes = [IsAuthenticated]
    authentication_classes = [JWTAuthentication]

    def create(self, request, *args, **kwargs):
        logging.info(f"FGR pushes order detail: {request.data}")
        data = {"successOrder": [], "failOrder": []}
        message = ""
        extra = None

        source = request.data.get("source", None)
        logging.info(f"source: {source}")
        
        all_order_data = request.data.get("orders", None)

        if not all_order_data:
            logging.error(f"No orders data: {all_order_data}")
            message += "Fail to get orders"
            return fgr_response(status.HTTP_201_CREATED, message, data, extra)

        # Create a list to store the new ProductionActualBOM instances
        for order_data in all_order_data:
            logging.info(f"order_data: {order_data}")
            success = True
            orderNo = ""
            try:
                orderNo = order_data["order"]
                logging.info("Create orderNo {}".format(orderNo))
                Article = order_data["Article"]
                order_data["ori_fg_article"] = Article
                ProdStandardBOMs = order_data["ProdStandardBOMs"]

                master_obj = common.get_master_obj(Article, order_data["design"], order_data["mould"], order_data["gold_type"])

                if master_obj:
                    logging.info(f"Master exists, assing to order")
                else:
                    logging.info(f"Master does not exist, add order {orderNo} to outstanding order")
                    master_obj, created = routes.Master.objects.get_or_create(fg_article=Article)
                    out_obj, created_outstanding = routes.OutstandingMaster.objects.update_or_create(
                        order=order_data["order"],
                        fg_article=Article,
                        defaults={
                            "design": order_data["design"],
                            "mould": order_data["mould"],
                            "gold_type": order_data["gold_type"],
                        },
                    )
                    if created_outstanding:
                        logging.info("Created outstanding master: {}".format(out_obj))

                order_data["master"] = master_obj.pk
                site_obj, _ = users.Site.objects.get_or_create(name=order_data["site"])
                order_data["site"] = site_obj.pk

            except Exception as e:
                logging.error(
                    f"Exception for DetailViewSet - orders: {e} for order {orderNo}."
                )
                message += "Fail to get order "
                data["failOrder"].append(orderNo)
                success = False

            order_data["updated_due_date"] = is_valid_datetime(
                order_data["updated_due_date"]
            )

            ready_date_str = order_data["ready_date"]
            if ready_date_str:
                ready_date = datetime.strptime(ready_date_str, "%Y/%m/%d %H:%M:%S") 

                # Convert the datetime to the expected format
                formatted_ready_date = ready_date.isoformat().replace("T", " ")

                # Update the order_data dictionary with the formatted ready_date
                order_data["ready_date"] = formatted_ready_date
            else:
                order_data["ready_date"]=None
            # print("order_data", order_data)

            order_data["source"] = source
            order_data["flower_count"] = order_data["Huatou"] if "Huatou" in order_data else None


            if success:
                try:
                    instance = Detail.objects.get(order=orderNo)
                    serializer = self.serializer_class(instance, data=order_data)
                except Detail.DoesNotExist:
                    serializer = self.serializer_class(data=order_data)
                    logging.info(f"Detail for order order {orderNo} does not exist")
                except Exception as e:
                    serializer = self.serializer_class(data=order_data)
                    logging.error(f"Fail to get order {orderNo} ")

                # If the serializer is valid, create a new ProductionActualBOM instance and add it to the list
                # if serializer.is_valid(raise_exception=True):
                if serializer.is_valid():
                    logging.debug(f"Detail serializer is valid for order {orderNo}: {order_data}")
                    instance = serializer.save()
                else:
                    logging.debug("Detail Serializer is not valid")
                    logging.error(f"{serializer.errors} for order {orderNo}.")
                    success = False
                    # message+="Fail to get {} for order {}. ".format(list(serializer.errors.keys())[0], orderNo)
                    message += "Fail to add detail for order {}. ".format(orderNo)

                if success:
                    # check or create order routing
                    logging.info("check or create order routing")
                    common.check_or_create_order_routing(instance)
                    # common.get_last_order_flow_record(instance)


                    logging.info("Get data for standardbom")
                    for standard_bom in order_data["ProdStandardBOMs"]:
                        standard_bom["workorder"] = instance.pk
                    logging.info(
                        f"ProdStandardBOMs for order {orderNo}: {order_data['ProdStandardBOMs']}"
                    )
                    standard_serializer = StandardBomSerializer(
                        data=order_data["ProdStandardBOMs"], many=True
                    )
                    if standard_serializer.is_valid():
                        instance = standard_serializer.save()
                    else:
                        logging.info("standard_serializer is not valid")
                        logging.error(f"{standard_serializer.errors} for order {orderNo}.")
                        success=False
                        message+="Fail to add standardbom for order {}. ".format(orderNo)


                if success:
                    data["successOrder"].append(orderNo)
                else:
                    data["failOrder"].append(orderNo)

        if not message:
            message = "Success"
            return fgr_response(status.HTTP_200_OK, message, data, extra)
        else:
            return fgr_response(status.HTTP_201_CREATED, message, data, extra)


@extend_schema_view(
    create=extend_schema(summary="Create or update actual bom for orders"),
)
class ActualBomModelViewSet(ModelViewSet):
    queryset = ProductionActualBOM.objects.none()
    serializer_class = ActualBomSerializer

    http_method_names = ["post"]
    permission_classes = [IsAuthenticated]
    authentication_classes = [JWTAuthentication]

    def create(self, request, *args, **kwargs):
        data = {"successOrder": [], "failOrder": []}

        all_actual_bom_data = request.data["ActualBom"]

        # Create a list to store the new ProductionActualBOM instances
        for order_data in all_actual_bom_data:
            orderNo = order_data["OrderNo"]
            TotalCount = order_data["TotalCount"]
            TotalCT = order_data["TotalCT"]
            TotalGram = order_data["TotalGram"]
            stoneIssue = order_data["stoneIssue"]
            # Huatou = order_data["Huatou"] if "Huatou" in order_data else None

            logging.info(f"Create actualbom for order {orderNo}")

            # update count in Detail
            detail_obj = Detail.objects.get(order=orderNo)
            detail_obj.total_count = TotalCount
            detail_obj.total_ct = TotalCT
            detail_obj.total_gram = TotalGram
            detail_obj.stone_issue = stoneIssue
            detail_obj.save()
            logging.info(
                f"Update total_count, total_ct and total_gram for order {orderNo}"
            )

            actualBomMappings = order_data["actualBomMappings"]

            success = True

            for bom_mapping in actualBomMappings:
                # Add the workorder ID to the dictionary
                bom_mapping["workorder"] = orderNo

                # Create a validated serializer instance for the dictionary
                # print(bom_mapping)
                serializer = self.serializer_class(data=bom_mapping)

                # If the serializer is valid, create a new ProductionActualBOM instance and add it to the list
                if serializer.is_valid():
                    new_instance = serializer.save()
                else:
                    print("Serializer is not valid")
                    logging.error(f"{serializer.errors} for order {orderNo}.")

                    success = False

            if success:
                data["successOrder"].append(orderNo)
            else:
                data["failOrder"].append(orderNo)

        message = "Success"
        extra = None
        return fgr_response(status.HTTP_201_CREATED, message, data, extra)


# 3.4	updateProdWeight

def insert_actual_weight(goldWeight, route_detail_obj, state):
    objs=[]
    for data in goldWeight:
        article = data["article"]
        actual_weight = data["weight"]
        objs.append(order_routing.ActualWeight(
            actual_weight=actual_weight,
            article=article,
            route_detail=route_detail_obj,
            state = state
        ))

    order_routing.ActualWeight.objects.bulk_create(objs)

def skip_flow_update_routedetail(route_detail_objs, skip_seq):
    """把跳过的单设置为完成, 清空Record记录中正在进行的信息"""
    first_route_detail_obj = None # 跳过后需要开始的flow
    route_record_obj = None # 记录
    for route_detail_obj in route_detail_objs:

        # 跳过的单设置成完成
        if skip_seq >= route_detail_obj.seq:
            # 清空之前的数据
            lastest_order_route_records = route_detail_obj.record_set.all()
            if lastest_order_route_records:
                lastest_order_route_records.update(worker=None, qc_check=None, leader_check=None, stone_check=None)

            route_detail_obj.status = 3
            route_detail_obj.save()
        
        if (skip_seq + 1 ) == route_detail_obj.seq:
            first_route_detail_obj = route_detail_obj
        
        record_obj = order_routing.Record.objects.filter(route_detail=route_detail_obj)
        if record_obj.exists():
            route_record_obj = record_obj.first()
    return first_route_detail_obj, route_record_obj

def skip_flow_update_record(route_detail_obj: order_routing.RouteDetail, route_record_obj: order_routing.Record):
    """把记录里开始的位置设置为跳过后的位置"""
    scan_and_record=route_detail_obj.flow.scan_and_record
    qc_check=route_detail_obj.flow.qc_check
    leader_check=route_detail_obj.flow.leader_check
    stone_check=route_detail_obj.flow.stone_exam

    if scan_and_record:
        worker_obj=order_routing.WorkerRecord.objects.create()
    else:
        worker_obj=None
    
    if qc_check:
        qc_check_obj=order_routing.CheckRecord.objects.create(check_type=1)
    else:
        qc_check_obj=None

    if leader_check:
        leader_check_obj=order_routing.CheckRecord.objects.create(check_type=2)
    else:
        leader_check_obj=None

    if stone_check:
        stone_check_obj=order_routing.CheckRecord.objects.create(check_type=3)
    else:
        stone_check_obj=None
    route_record_obj.route_detail=route_detail_obj
    route_record_obj.worker = worker_obj
    route_record_obj.qc_check = qc_check_obj
    route_record_obj.stone_check = stone_check_obj
    route_record_obj.leader_check = leader_check_obj
    route_record_obj.save()

class ProdWeightViewSet(ViewSet):
    # queryset = Dispatcher.objects.none()
    # serializer_class = ActualBomSerializer

    http_method_names = ["post"]
    permission_classes = [IsAuthenticated]
    authentication_classes = [JWTAuthentication]

    # TODO: not yet handle consumption_percentage and worker_fee
    
    """
        {
        "order": "10006",
        "deptCode":"F2F0000",
        "userCode":"F2FS001",
        "goldWeight":[
            {"article":"", "weight":1.2},
            {"article":"", "weight":2.3}
        ] ,
        "consumption_percentage": 1.0,  
        "worker_fee": 1.0,
        "state":1
        }
    """

    def create(self, request, *args, **kwargs):
        data = None
        extra = None
        message = "Success"
        route_detail_obj=None

        orderNo = request.data["order"]
        deptCode = request.data["deptCode"]
        userCode = request.data["userCode"]
        goldWeight = request.data["goldWeight"]
        state = request.data["state"]
        center_sender = request.data.get("centersender", None)
        is_gold_init = request.data.get("isgoldinit", None)
        bypass = request.data.get("bypass", False)

        logging.info(f"FGR push the production weight: {request.data}")

        try:
            detail_obj = Detail.objects.get(order=orderNo)
        except Detail.DoesNotExist:
            return fgr_response(status.HTTP_201_CREATED,  "订单不可用", None,"Fail")
        
        if state == 3:
            # 跳过单, 并继承weight

            # 1.获取最后一个出水
            all_route_detail_objs = order_routing.RouteDetail.objects.filter(order_route__workorder__order=orderNo)
            skip_flow_objs = all_route_detail_objs.filter(flow__chinese_name='出水') 
            skip_seq = 0
            skip_flow_obj = None
            if skip_flow_objs.exists():
                skip_flow_obj = skip_flow_objs.last()
                skip_seq = skip_flow_obj.seq
            else:
                return fgr_response(status.HTTP_201_CREATED, "流程中没有出水", data, extra)

            # 2.找到要开始的位置, 清空其他数据
            first_route_detail_obj, route_record_obj = skip_flow_update_routedetail(all_route_detail_objs, skip_seq)

            # 3.设置重新开始的位置, 继承goldWeight(这里state=1才显示数据)
            if first_route_detail_obj and route_record_obj:
                skip_flow_update_record(first_route_detail_obj, route_record_obj)

                insert_actual_weight(goldWeight, skip_flow_obj, state=3)

        else:
            route_detail_objs = order_routing.RouteDetail.objects.none()
            if bypass == False:
                if err_message := common.check_flow_is_ok(detail_obj):
                    return fgr_response(status.HTTP_201_CREATED, err_message, None, "Fail")

            if is_gold_init:
                route_detail_objs = order_routing.RouteDetail.objects.filter(
                        order_route__workorder__order=orderNo, status=2
                    )
                
                account_obj = None
                
            else:
                account_obj = users.Account.objects.filter(
                    user_code=userCode, department__code=deptCode
                ).first()
                if account_obj:
                    if account_obj.department.site.name != detail_obj.source:                   
                        return fgr_response(status.HTTP_201_CREATED, "账户地点与订单不符", None, "Fail")

                    # Get the route_detail_obj for the flow and in progress
                    route_detail_objs = order_routing.RouteDetail.objects.filter(
                        flow=account_obj.department.flow, order_route__workorder__order=orderNo, status=2
                    )

            if route_detail_objs.exists():
                logging.info(f"Get RouteDetail for {orderNo}: {route_detail_objs}")
                try:
                    route_detail_obj = route_detail_objs.get()
                except Exception as e:
                    logging.error(f"Fail to get one RouteDetail for {orderNo}: {e}")
            else:
                flow = account_obj.department.flow if hasattr(account_obj, 'department') else 'is gold init'
                logging.info(f"No RouteDetail of {orderNo} for Flow {flow} with status=2")
                message = f"Fail to update since order {orderNo} for flow {flow} is not in progress."

            if route_detail_obj:
                logging.info(f"RouteDetail obj for update the production weight: {route_detail_obj}")
                dispatch_obj = route_detail_obj.dispatcher
                logging.info(f"dispatch_obj: {dispatch_obj}")
                if not dispatch_obj:
                    dispatch_obj=order_routing.Dispatcher.objects.create()
                    logging.info(f"Create new dispatch for {dispatch_obj}")
                    route_detail_obj.dispatcher=dispatch_obj
                    route_detail_obj.save(update_fields={"dispatcher"})
                
                if state == 0:
                    logging.info(f"State is {state} - Worker to dispatcher. First step of flow")
                    dispatch_obj.start_account = account_obj
                    dispatch_obj.centersender = center_sender
                    dispatch_obj.end_at = timezone.now()
                    # dispatch_obj.start_weights = json.dumps(goldWeight)
                    dispatch_obj.save()
                    insert_actual_weight(goldWeight, route_detail_obj, state)

                    route_detail_obj.order_route.holder=account_obj
                    route_detail_obj.order_route.holder_record_time=timezone.now()
                    route_detail_obj.order_route.save(update_fields={"holder", "holder_record_time"})
                    return fgr_response(status.HTTP_200_OK, message, data, extra)
                elif state == 1:
                    logging.info(f"State is {state} - Worker to dispatcher. Last step of flow")
                    dispatch_obj.end_account = account_obj
                    dispatch_obj.centersender = center_sender
                    dispatch_obj.end_at = timezone.now()
                    # dispatch_obj.end_weights = json.dumps(goldWeight)
                    dispatch_obj.save()
                    insert_actual_weight(goldWeight, route_detail_obj, state)


                    route_detail_obj=common.update_route_status(route_detail_obj, 3)

                    route_detail_obj.order_route.holder=None
                    route_detail_obj.order_route.holder_record_time=timezone.now()
                    route_detail_obj.order_route.save(update_fields={"holder", "holder_record_time"})

                    # logging.info(f"Check and create record for next flow")
                    # common.create_record_for_next_flow_for_dispatcher(route_detail_obj)
                    return fgr_response(status.HTTP_200_OK, message, data, extra)
                elif state == 2:
                    if account_obj.department.flow.name=="PF":
                        logging.info(f"State is {state} - PF state - Remove holder")
                        route_detail_obj.order_route.holder=None
                        route_detail_obj.order_route.holder_record_time=timezone.now()
                        route_detail_obj.order_route.save(update_fields={"holder", "holder_record_time"})
                        # TODO: Set detail_obj status to complete
                        
                    else:
                        message = f"User[{userCode}] deptCode[{deptCode}] is not PF department. No update."
                        logging.info(f"{message}")
                        return fgr_response(status.HTTP_201_CREATED, message, data, extra)


            else:
                if not is_gold_init:
                    logging.info(
                        f"Fail to get account with userCode={userCode} and deptCode={deptCode}"
                    )
                    message = f"No account record for userCode={userCode} deptCode={deptCode}"
                    return fgr_response(status.HTTP_201_CREATED, message, data, extra)

        return fgr_response(status.HTTP_200_OK, message, data, extra)


# 3.5	startWorkerFlow
@extend_schema_view(
    create=extend_schema(summary="Start worker flow"),
)
class StartWorkerFlowViewSet(ViewSet):
    # queryset = Dispatcher.objects.none()
    # serializer_class = ActualBomSerializer

    http_method_names = ["post"]
    permission_classes = [IsAuthenticated]
    authentication_classes = [JWTAuthentication]

    def create(self, request, *args, **kwargs):
        data = None

        orderNo = request.data["order"]

        message = "Success"
        extra = None
        return fgr_response(status.HTTP_200_OK, message, data, extra)


# 3.6	updatePrintStatus
@extend_schema_view(
    create=extend_schema(summary="Send printer status"),
)
class PrintStatusViewSet(ViewSet):
    # queryset = Dispatcher.objects.none()
    # serializer_class = ActualBomSerializer

    http_method_names = ["post"]
    permission_classes = [IsAuthenticated]
    authentication_classes = [JWTAuthentication]

    def create(self, request, *args, **kwargs):
        data = None
        extra = None
        message = "Success"

        ##printSuccessOrders = request.data["printSuccessOrders"]
        ##printFailOrders = request.data["printFailOrders"]
        ##printerId = request.data["printerId"]
        department = request.data["dept"]
        orders = request.data["orders"]

        now = timezone.now()
        if department == 1:
            logging.info("update gold_print_date")
            detail_objs = Detail.objects.filter(
                order__in=orders, gold_print_date__isnull=True
            )
            if detail_objs.exists():
                logging.info(f"update work order gold print data: {detail_objs}")
                detail_objs.update(gold_print_date=now)

        else:
            logging.info("update stone_print_date")
            detail_objs = Detail.objects.filter(
                order__in=orders, stone_print_date__isnull=True
            )
            if detail_objs.exists():
                logging.info(f"update work order stone print data: {detail_objs}")
                detail_objs.update(stone_print_date=now)

        return fgr_response(status.HTTP_200_OK, message, data, extra)


# 3.7	updatePFStatus


@extend_schema_view(
    create=extend_schema(summary="Set order PF status"),
)
class PFStatusViewSet(ViewSet):
    http_method_names = ["post"]
    permission_classes = [IsAuthenticated]
    authentication_classes = [JWTAuthentication]

    def create(self, request, *args, **kwargs):
        data = None
        extra = None
        message = "Success"

        orderNo = request.data["order"]
        PFStatus = request.data["PFStatus"]
        PFDate = request.data["PFDate"]
        

        try:
            detail_obj = Detail.objects.get(order=orderNo)
            order_routing_obj = order_routing.OrderRouting.objects.get(workorder=detail_obj.order)
            route_detail_queryset = order_routing.RouteDetail.objects.filter(order_route=order_routing_obj, status=1) # 因为PF变成了open, 所以先找status=1

        except Detail.DoesNotExist:
            message = "order is not available"
        else:
            if route_detail_queryset.exists():
                route_detail_obj = route_detail_queryset.first()
                common.update_route_status(route_detail_obj, 3)
            common.update_order_state(detail_obj, 1)
            common.update_order_complete_date(order_routing_obj,PFDate)
            message = "Success"

        return fgr_response(status.HTTP_200_OK, message, data, extra)


# 3.8 queryOrderRoutingInfo


@extend_schema_view(
    create=extend_schema(summary="Retrieve order master routing information"),
)
class queryOrderRoutingInfo(ModelViewSet):
    queryset = order_routing.RouteDetail.objects.none()
    serializer_class = RouteDetailSerializer

    http_method_names = ["get"]
    permission_classes = [IsAuthenticated]
    authentication_classes = [JWTAuthentication]

    def get_object(self):
        # queryset = self.filter_queryset(self.get_queryset())
        try:
            detail_obj = Detail.objects.get(pk=self.kwargs["pk"])
            return detail_obj
        except Exception as e:
            logging.info(f"Order {self.kwargs['pk']} is not available")
            return None

    def retrieve(self, request, pk, *args, **kwargs):
        data = []
        extra = None
        message = "Success"

        detail_obj = self.get_object()

        if detail_obj:
            logging.info("Order exists")
            try:
                routedetail_objs = detail_obj.orderrouting.routedetail_set.all()
                data = self.serializer_class(routedetail_objs, many=True).data
                logging.debug(f"RouteDetailSerializer data: {data}")
            except Exception as e:
                logging.info(f"No order routing table for {detail_obj}")
        else:
            message = "order is not available"

        return fgr_response(status.HTTP_200_OK, message, data, extra)

# 3.7	updatePFStatus


@extend_schema_view(
    create=extend_schema(summary="Discard order"),
)
class DiscardOrderView(ModelViewSet):
    http_method_names = ["put"]
    permission_classes = [IsAuthenticated]
    authentication_classes = [JWTAuthentication]
    queryset = Detail.objects.all()
    # serializer_class = DiscardDetailSerializer
    
    def get_object(self):
        try:
            obj = self.queryset.get(order=self.kwargs["pk"])
            return obj
        except Exception as e:
            logging.info(f"Fail to get order: {e}")
            return None

    def update(self, request, pk, *args, **kwargs):
        logging.info(f"Discard order")
        data=None
        instance = self.get_object()
        logging.info(f"Discard order: {instance}")

        if instance:
            state_data={"state":2}
            serializer = DiscardDetailSerializer(instance, data=state_data, partial=True)
            # serializer = self.get_serializer(instance, data=request.data, partial=True)
            
            if serializer.is_valid():
                serializer.save()
                message="Success"
            else:
                message = "Fail"
                logging.error(
                    f"Fail to update order {instance} state to 2 : {serializer.errors} "
                )
                return fgr_response(status.HTTP_201_CREATED, message, data)
        
            return fgr_response(status.HTTP_200_OK, message, data)
        else:
            message = "Fail"
            logging.error(
                f"Fail to get order {instance} and cannot discard order."
            )
            return fgr_response(status.HTTP_201_CREATED, message, data)


    # def update(self, request, pk, *args, **kwargs):
    #     message = "Success"
    #     data = {}
    #     serializer = self.get_serializer(
    #         check_record_obj, data=request.data, partial=True
    #     )

    #     if serializer.is_valid():
    #         account_obj = serializer.validated_data.get("account")
    #     else:
    #         message = "Fail"
    #         logging.error(
    #             f"QCActionSerializer is invalid for CheckRecord {pk}: {serializer.errors} "
    #         )
    #         return frontend_response(status.HTTP_200_OK, message, data)

    #     detail_obj = frontend_lib.filter_detail_obj_by_check_record(check_record_obj)
    #     last_order_flow_record_obj = common.get_last_order_flow_record(detail_obj)
    #     if not common.check_user_can_change_status(
    #         detail_obj, last_order_flow_record_obj, account_obj
    #     ):
    #         logging.info(
    #             f"{account_obj} is not allowed to change status of the order {detail_obj}"
    #         )
    #         message = f"{account_obj.django_user.cnName} is not allowed to change status of the order {detail_obj}"
    #         return frontend_response(status.HTTP_200_OK, message, data)

    #     if common.check_qc_record_editable(check_record_obj):
    #         logging.info(f"QCActionSerializer is valid for CheckRecord {pk}.")
    #         # check if failed reason is selected
    #         qc_valid=serializer.check_fail_reason()
    #         logging.info(f"{qc_valid=}")
    #         if qc_valid:
    #             self.perform_update(serializer)
    #             check_record_obj.refresh_from_db()  # refresh the instance from the database to get the latest version
    #             if not check_record_obj.failed:
    #                 common.update_route_detail_status(check_record_obj)
    #         else:
    #             logging.info(f"QC result is not valid. Please select reason.")
    #             message = "Fail"

    #     else:
    #         logging.info(
    #             f"{check_record_obj} is already submitted. Don't update result"
    #         )

    #     return fgr_response(status.HTTP_200_OK, message, data, extra)

